#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include "utilities.h"
#include <QMessageBox>


using namespace cv;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , capturer(nullptr)
{
    ui->setupUi(this);
    this->SktInitCmaSys();

    m_pQLabel[16]={NULL};


    m_pCurLbl=NULL;

    data_lock = new QMutex();

    cameraHandler[1024]={0};



    //m_rpsliderflag = 1;
    m_rpptzspeed = 4;
    m_ptzupswitch = 0;
    m_ptzdownswitch = 0;
    m_ptzrghtswitch = 0;
    m_ptzleftswitch = 0;
    m_ptznarrowswitch = 0;
    m_ptzexpandswitch = 0;
    m_ptzfarswitch = 0;
    m_ptznearswitch = 0;
    m_ptzbigswitch = 0;
    m_ptzsmallswitch = 0;
//    m_rpstartstopflag = 0;
//    m_rpsavestopflag = 0;

//    m_ptzpreset = NULL;
//    m_ptzcruise = NULL;
//    m_ptzpresetpointindex = 1;
//    m_ptzcruisepathindex = 1;
//    m_ptzcruiserunning = 0;




}

MainWindow::~MainWindow()
{
    delete ui;
}

/**
 * @brief MainWindow::SktInitCmaSys 用于初始化窗口、按钮
 */
void  MainWindow::SktInitCmaSys(){

    QEvent *event=new QEvent(QEvent::Resize);//安装监听器
    ui->topWdt->installEventFilter(this);
    this->eventFilter(ui->topWdt,event);


    MainWindow::setWindowFlag(Qt::FramelessWindowHint);
    ui->leftWdt->setStyleSheet("background-color:#d7d7d7;");
    ui->controlWdt->setStyleSheet("background-color:#5D5E5D;");



    SktSetBtnStyle(ui->closeBtn,"://SktPicPath/icon_close.png","://SktPicPath/icon_closeh.png","://SktPicPath/icon_closez.png");
    SktSetBtnStyle(ui->minBtn,"://SktPicPath/icon_small.png","://SktPicPath/icon_smallh.png","://SktPicPath/icon_smallz.png");
    SktSetBtnStyle(ui->maxBtn,"://SktPicPath/icon_down.png","://SktPicPath/icon_downh.png","://SktPicPath/icon_downz.png");
    //////////////右边按钮
    ///

    SktSetBtnStyle(ui->scr1Btn,"://SktPicPath/icon_01.png","://SktPicPath/icon_01h.png","://SktPicPath/icon_01h.png");
    SktSetBtnStyle(ui->scr4Btn,"://SktPicPath/icon_02.png","://SktPicPath/icon_02h.png","://SktPicPath/icon_02h.png");
    SktSetBtnStyle(ui->scr8Btn,"://SktPicPath/icon_03.png","://SktPicPath/icon_03h.png","://SktPicPath/icon_03h.png");
    SktSetBtnStyle(ui->scr16Btn,"://SktPicPath/icon_04.png","://SktPicPath/icon_04h.png","://SktPicPath/icon_04h.png");

    SktSetBtnStyle(ui->fullScrBtn,"://SktPicPath/icon_maxh.png","://SktPicPath/icon_max.png","://SktPicPath/icon_maxh.png");
    SktSetBtnStyle(ui->stopBtn,"://SktPicPath/2d12.png","://SktPicPath/2d11.png","://SktPicPath/2d12.png");




    //SktSetBtnStyle(ui->controlTitleWdt,"","","");

    SktLoadQssFile("://SktQssFile.css");

    ui->logoLbl->setPixmap(QPixmap(":/SktPicPath/logo.png"));

    SktSetSignal();

    QAction *searchAction =new QAction(ui->findEdt);
    searchAction->setIcon(QIcon("://SktPicPath/icon_Load .png"));
    ui->findEdt->addAction(searchAction,QLineEdit::TrailingPosition);

    SktAddCmaList();

        ////////////
    ///加入新的通道label处理
    ///
    ///
    m_pQLabel[0]=ui->lbl1;
    m_pQLabel[0]->installEventFilter(this);

    m_pQLabel[1]=ui->lbl2;
     m_pQLabel[1]->installEventFilter(this);


    m_pQLabel[2]=ui->lbl3;
     m_pQLabel[2]->installEventFilter(this);

    m_pQLabel[3]=ui->lbl4;
     m_pQLabel[3]->installEventFilter(this);

    m_pQLabel[4]=ui->lbl5;
     m_pQLabel[4]->installEventFilter(this);

    m_pQLabel[5]=ui->lbl6;
     m_pQLabel[5]->installEventFilter(this);

    m_pQLabel[6]=ui->lbl7;
     m_pQLabel[6]->installEventFilter(this);

    m_pQLabel[7]=ui->lbl8;
     m_pQLabel[7]->installEventFilter(this);

    m_pQLabel[8]=ui->lbl9;
     m_pQLabel[8]->installEventFilter(this);

    m_pQLabel[9]=ui->lbl10;
     m_pQLabel[9]->installEventFilter(this);

    m_pQLabel[10]=ui->lbl11;
     m_pQLabel[10]->installEventFilter(this);

    m_pQLabel[11]=ui->lbl12;
     m_pQLabel[11]->installEventFilter(this);

    m_pQLabel[12]=ui->lbl13;
     m_pQLabel[12]->installEventFilter(this);


    m_pQLabel[13]=ui->lbl14;
     m_pQLabel[13]->installEventFilter(this);


    m_pQLabel[14]=ui->lbl15;
     m_pQLabel[14]->installEventFilter(this);


    m_pQLabel[15]=ui->lbl16;
     m_pQLabel[15]->installEventFilter(this);




    SktInitAllLbl();



}

/**
 * @brief MainWindow::setLablWH 保存lables的宽和高
 */
void MainWindow::setLablWH(){
//    for(int i=0;i<16;i++){
//        m_oLblWH[i]=Size(m_pQLabel[i]->width(),m_pQLabel[i]->height());

//    }

    if(nullptr!=m_pCurLbl){

        m_oCurrentLblSize=Size(m_pCurLbl->width(),m_pCurLbl->height());
        qDebug()<<"save new window size:"<<m_pCurLbl->width()<<","<<m_pCurLbl->height()<<endl;

    }


}
void MainWindow::SktInitAllLbl(){
    for(int i=0;i<16;i++){
        m_pQLabel[i]->setStyleSheet("background-color:#B8B7B7;");
    }
}

 void  MainWindow::paintEvent(QPaintEvent *){
     QPainter painter(this);
     painter.drawPixmap(0,0,this->width(),this->height(),m_oQPixmap);

}
 void MainWindow::mousePressEvent(QMouseEvent *event){
     if(event->button() == Qt::LeftButton){
         m_oQPoint = event->globalPos() -frameGeometry().topLeft();
         event->accept();
     }

}

 void MainWindow::mouseMoveEvent(QMouseEvent* event){
     if(event->buttons() && Qt::LeftButton){
         QPoint oGlobalPoint=event->globalPos();
         QPoint oMovePoint= oGlobalPoint -m_oQPoint;
         move(oMovePoint);
         event->accept();
     }

}
 /**
  * @brief MainWindow::SktCloseBtnSlots exit application
  */
 void MainWindow::SktCloseBtnSlots(){
     QCoreApplication::exit();

 }
 void MainWindow::SktMaxBtnSlots(){
     if(isMaximized()){
         MainWindow::showNormal();
     }else{
         MainWindow::setWindowState(Qt::WindowMaximized);
     }



 }
 void MainWindow::SktMinBtnSlots(){

     MainWindow::showMinimized();
     qDebug() <<"min btn...";

 }

 void MainWindow::SktIndexBtnSlots(){
     ui->indexBtn->setIcon(QIcon("://SktPicPath/icon_homeh.png"));
      ui->videoBtn->setIcon(QIcon("://SktPicPath/icon_jiankong .png"));

      ui->SktStackWdt->setCurrentWidget(ui->p1);

 }
 void MainWindow::SktVideoBtnSlots(){
     ui->indexBtn->setIcon(QIcon("://SktPicPath/icon_home.png"));
      ui->videoBtn->setIcon(QIcon("://SktPicPath/icon_jiankong h.png"));
      ui->SktStackWdt->setCurrentWidget(ui->p2);
 }



 /**
  * @brief MainWindow::SktSetSignal 信号关联
  */

 void MainWindow::SktSetSignal(){
     connect(ui->closeBtn,SIGNAL(clicked()),this,SLOT(SktCloseBtnSlots()));
     connect(ui->minBtn,SIGNAL(clicked()),this,SLOT(SktMinBtnSlots()));
     connect(ui->maxBtn,SIGNAL(clicked()),this,SLOT(SktMaxBtnSlots()));

     connect(ui->indexBtn,SIGNAL(clicked()),this,SLOT(SktIndexBtnSlots()));
     connect(ui->videoBtn,SIGNAL(clicked()),this,SLOT(SktVideoBtnSlots()));

     connect(ui->camListWdt,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(SktCmaTreeWdtSlot(QTreeWidgetItem*,int)));

     connect(ui->fullScrBtn,SIGNAL(clicked()),this,SLOT(SktFullScreenSlots()));//全屏

     connect(ui->ptzLeftBtn,SIGNAL(clicked()),this,SLOT(SktPTZLeftSlots()));//left ptz
     connect(ui->ptzRightBtn,SIGNAL(clicked()),this,SLOT(SktPTZRightSlots()));//right ptz

     connect(ui->ptzUpBtn,SIGNAL(clicked()),this,SLOT(SktPTZUpSlots()));//up ptz

     connect(ui->ptzDownBtn,SIGNAL(clicked()),this,SLOT(SktPTZDownSlots()));//down ptz


 }


 void MainWindow::SktAddCmaList(){

     QTreeWidgetItem *itemRoot = new QTreeWidgetItem(ui->camListWdt,QStringList(QString::fromLocal8Bit("测试监控")));
     itemRoot->setIcon(0,QIcon("://SktPicPath/1.png"));

     QTreeWidgetItem *itemSub = new QTreeWidgetItem(itemRoot,QStringList(QString::fromLocal8Bit("192.168.1.67")));
     itemSub->setIcon(0,QIcon("://SktPicPath/3.png"));
     itemRoot->addChild(itemSub);

     ui->camListWdt->expandAll();


     SktAddSubItem(itemRoot,"192.168.1.100","://SktPicPath/3.png");



 }

 void MainWindow::SktAddSubItem(QTreeWidgetItem *pRootItem,
                                const char *pstIp,const char * pstPicPath){

     QTreeWidgetItem *pSubItem = new QTreeWidgetItem(pRootItem,QStringList(QString::fromLocal8Bit(pstIp)));
     pSubItem->setIcon(0,QIcon(pstPicPath));
     pRootItem->addChild(pSubItem);

      ui->camListWdt->expandAll();



 }

 /**
  * @brief MainWindow::SktSetCurLblMax 最大化/还原当前通道
  */
 void MainWindow::SktSetCurLblMax(){

     m_bIsMax = !m_bIsMax;
     for(int i=0;i<16;i++){
         m_pQLabel[i]->setVisible(!m_bIsMax);
     }

     m_pCurLbl->setVisible(true);


     setLablWH();//保存更改后的label窗口大小


 }

 bool MainWindow::eventFilter(QObject *watched, QEvent *event){

      QMouseEvent *pMouseEvent = static_cast<QMouseEvent *>(event);

     if(QEvent::Resize == event->type()){

     }

     if(event->type() ==QEvent::MouseButtonDblClick && (pMouseEvent->buttons()==Qt::LeftButton) ){
         SktSetCurLblMax();//设置当前通道最大化
     }

     if(event->type()==QEvent::MouseButtonPress){



         if(pMouseEvent->buttons()==Qt::LeftButton){
             m_pCurLbl= qobject_cast<QLabel *>(watched);
             if(NULL == m_pCurLbl){

                  return QObject::eventFilter(watched,event);
             }

             SktInitAllLbl();
             m_pCurLbl->setFocus();
             m_pCurLbl->setStyleSheet("background-color:white;");


             setLablWH();//保存更改后的label窗口大小

         }
     }

     return QObject::eventFilter(watched,event);
 }

 /**
  * @brief 加入对点击摄像头树的信号处理
  */
 void  MainWindow::SktCmaTreeWdtSlot(QTreeWidgetItem *pSubTree,int k){
     QTreeWidgetItem *pRootTree = pSubTree->parent();
     if(NULL == pRootTree){
         return ;
     }
     QString qsRoot =pRootTree->text(k);
     QString strMsg =pSubTree->text(k);

     int k1=0;
     //
     if(linkHik()){

         openCamera();

     }
         ;

 }

void CALLBACK ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser){
    qDebug("ExceptionCallBack lUserID:%d, handle:%d, user data:%p", lUserID, lHandle, pUser);

       char tempbuf[256];
       memset(tempbuf, 0, 256);
       switch(dwType)
       {
       case EXCEPTION_AUDIOEXCHANGE:		//Audio exchange exception
           sprintf(tempbuf,"Audio exchange exception!");

           //TODO: close audio exchange
           break;

       //Alarm//
       case EXCEPTION_ALARM:			            //Alarm exception
           sprintf(tempbuf,"Alarm exception!");

           //TODO: close alarm update
           break;
       case EXCEPTION_ALARMRECONNECT:  //Alarm reconnect
           sprintf(tempbuf,"Alarm reconnect.");

           break;
       case ALARM_RECONNECTSUCCESS:      //Alarm reconnect success
           sprintf(tempbuf,"Alarm reconnect success.");

           break;

       case EXCEPTION_SERIAL:			           //Serial exception
           sprintf(tempbuf,"Serial exception!");

           //TODO: close exception
           break;

       //Preview//
       case EXCEPTION_PREVIEW:			     //Preview exception
           sprintf(tempbuf,"Preview exception!");

           //TODO: close preview
           break;
       case EXCEPTION_RECONNECT:			 //preview reconnect
           sprintf(tempbuf,"preview reconnecting.");

           break;
       case PREVIEW_RECONNECTSUCCESS: //Preview reconnect success
           sprintf(tempbuf,"Preview reconncet success.");

           break;
       default:
           break;
       }

}
 bool MainWindow::linkHik(){
//    const  char *sIP ="192.168.1.67";
//         int iPort = 8000;
//     const    char *sUserName = "admin";
//      const   char *sPassword = "hik123456";
//         int iChannel = 1;

         //Init
            int iRet = NET_DVR_Init();
            if (!iRet)
            {
                printf("   linkHik. NET_DVR_Init fail!\n");
                return false;
            }

            //设置连接时间与重连时间
              NET_DVR_SetConnectTime(2000, 1);
              NET_DVR_SetReconnect(10000, true);
              //设置异常消息回调函数
                NET_DVR_SetExceptionCallBack_V30(0, NULL,ExceptionCallBack, NULL);

                //登录参数，包括设备地址、登录用户、密码等
                  NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
                  struLoginInfo.bUseAsynLogin = 0; //同步登录方式
                  strcpy(struLoginInfo.sDeviceAddress, QString("192.168.1.67").toLatin1().data()); //设备IP地址
                  struLoginInfo.wPort = 8000; //设备服务端口
                  strcpy(struLoginInfo.sUserName, QString("admin").toLatin1().data()); //设备登录用户名
                  strcpy(struLoginInfo.sPassword, QString("hik123456").toLatin1().data()); //设备登录密码

                  //设备信息, 输出参数
                  NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};

                 long lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
                  if (lUserID < 0)
                  {
                      qDebug()<<"Login failed, error code: "<< NET_DVR_GetLastError();
                      NET_DVR_Cleanup();
                      return false;
                  }

                  curCamHandler=lUserID;
                  qDebug()<<"open camera handle:"<<curCamHandler;
                  return true;





//          NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
//              NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};
//              struLoginInfo.bUseAsynLogin = false;

//              struLoginInfo.wPort = 8000;
//              memcpy(struLoginInfo.sDeviceAddress, "192.168.1.67", NET_DVR_DEV_ADDRESS_MAX_LEN);
//              memcpy(struLoginInfo.sUserName, "admin", NAME_LEN);
//              memcpy(struLoginInfo.sPassword, "hik12345", NAME_LEN);

//          int    lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);


//         if(lUserID >= 0)
//         {

//            return true;

//         }
//         else{
//             qDebug()<<"open camera handle error!"<<NET_DVR_GetLastError();
//             return  false;
//         }

 }


 /**
  * @brief MainWindow::SktFullScreenSlots 全屏
  */
 void MainWindow::SktFullScreenSlots(){

     SktShowHideOtherWdt(true);


 }

 /**
  * @brief MainWindow::SktShowHideOtherWdt真正的全屏或取消全屏的函数
  * @param isShow为true表示全屏
  */
 void MainWindow::SktShowHideOtherWdt(bool isShow){
     qDebug()<<isShow;

     ui->topWdt->setVisible(!isShow);
     ui->leftWdt->setVisible(!isShow);

     ui->rightTopWdt->setVisible(!isShow);
     ui->rightBottomWdt->setVisible(!isShow);

     if(isShow)
        MainWindow::showFullScreen();
     else
         MainWindow::setWindowState(Qt::WindowMaximized);


       setLablWH();

 }

 void  MainWindow::keyPressEvent(QKeyEvent *event){

     switch(event->key()){
     case Qt::Key_Escape:{
         SktShowHideOtherWdt(false);//取消全屏

     }
     default:
         QWidget::keyPressEvent(event);
         break;
     }


 }

 //---------------与多线程和opencv相关的内容

 void MainWindow::openCamera()
 {
     if(capturer != nullptr) {
         // if a thread is already running, stop it
         qDebug()<<"a thread is already running, stop it"<<endl;

         capturer->setRunning(false);
         disconnect(capturer, &CaptureThread::frameCaptured, this, &MainWindow::updateFrame);

         connect(capturer, &CaptureThread::finished, capturer, &CaptureThread::deleteLater);
     }
     // I am using my second camera whose Index is 2.  Usually, the
     // Index of the first camera is 0.
     int camID = 0;
     capturer = new CaptureThread(camID, data_lock);
     connect(capturer, &CaptureThread::frameCaptured, this, &MainWindow::updateFrame);

     capturer->start();
     qDebug()<<"open camera ...."<<endl;

 }
// //窗口变化了，那么需要重新保存当前label窗口的大小
// void MainWindow::resizeEvent(QResizeEvent *event)
// {

//     if(nullptr !=m_pCurLbl){
//        // setLablWH();//保存更改后的label窗口大小

//     }
//     this->update();
// }


 void MainWindow::updateFrame(cv::Mat *mat)
 {

     try {
         data_lock->lock();
         currentFrame = *mat;
         data_lock->unlock();

         //cv::cvtColor(currentFrame, gray, COLOR_BGR2GRAY); //转换为灰度图
    //     int width =m_pCurLbl->width();
    //     int height=m_pCurLbl->height();
    //     cv::resize(currentFrame,currentFrame,Size(width,height));
    //     qDebug()<< width<<","<<height;



         QImage frame(
             currentFrame.data,
             currentFrame.cols,
             currentFrame.rows,
             currentFrame.step,
             QImage::Format_RGB888);

    //     QImage frame(
    //         gray.data,
    //         gray.cols,
    //         gray.rows,
    //         gray.step,
    //         QImage::Format_RGB888);

        // qDebug()<<m_oCurrentLblSize.width<<","<<m_oCurrentLblSize.height;
          frame = frame.scaled(m_oCurrentLblSize.width,m_oCurrentLblSize.height);

         QPixmap image = QPixmap::fromImage(frame);


         m_pCurLbl->setPixmap(image);

     } catch (exception& e) {
         qDebug()<<"Exception:"<<e.what()<<endl;


     }

 }
 ////////////////////////////////////////////////
 // PTZ

 //left button
 void MainWindow::SktPTZLeftSlots()
 {

     if(curCamHandler>=0){
         if (m_ptzleftswitch == 0)
            {
                m_ptzleftswitch = 1;
            }
            else
            {
                m_ptzleftswitch = 0;
            }
            ptzControlRealPlay(PAN_LEFT,m_ptzleftswitch);
            qDebug()<<"left button";
     }

 }



 void MainWindow::SktPTZRightSlots(){

     if(curCamHandler>=0){
         if (m_ptzrghtswitch == 0)
             {
                 m_ptzrghtswitch = 1;
             }
             else
             {
                 m_ptzrghtswitch = 0;
             }
             ptzControlRealPlay(PAN_RIGHT,m_ptzrghtswitch);

              qDebug()<<"right button";
     }


 }

 void MainWindow::SktPTZUpSlots(){
     if(curCamHandler>=0){
         if (m_ptzupswitch == 0)
             {
                 m_ptzupswitch = 1;
             }
             else
             {
                 m_ptzupswitch = 0;
             }
             ptzControlRealPlay(TILT_UP,m_ptzrghtswitch);

              qDebug()<<"up button";
     }


 }
 void MainWindow::SktPTZDownSlots(){
     if(curCamHandler>=0){
         if (m_ptzdownswitch == 0)
             {
                 m_ptzdownswitch = 1;
             }
             else
             {
                 m_ptzdownswitch = 0;
             }
             ptzControlRealPlay(TILT_DOWN,m_ptzrghtswitch);

              qDebug()<<"up button";
     }
 }

 /************************************************************************
  *        Function            :  ptzControlRealPlay
  *        Description         :  ptz control
  *        Input               :  int command ��̨��������,int flag ����λ
  *        Output              :  none
  *        Return              :  none
 *************************************************************************/
 void MainWindow::ptzControlRealPlay(int command,int flag)
 {

     if (!NET_DVR_PTZControl_Other(curCamHandler,1L, command, flag))
     {
         QMessageBox::information(this,tr("NET_DVR_PTZControl Error"),
                 tr("SDK_LASTERROR=%1").arg(NET_DVR_GetLastError()));
     }
     qDebug()<<"ptz:"<<command;
 }




